iT邦幫忙

2021 iThome 鐵人賽

DAY 24
0
Mobile Development

Android 新手入門學習系列 第 24

Day24 Android - databinding(單向綁定)

  • 分享至 

  • xImage
  •  

databinding可用於將class的data與元件綁定,像是(findViewById、onClickListener)等UI綁定、監聽的代碼都可以用databinding來實現,在程式設計的越來越大時,算是相當好用的一個應用,那麼就開始今天的主題。

依賴

首先在gradle/android加入:

android {
    ...
    dataBinding {
        enabled = true
    }
}

等Sync now完之後就可以來更改布局。


布局

https://ithelp.ithome.com.tw/upload/images/20210907/20139259y61b63HV0I.png
在最外層的布局中按alt+enter就會跑出這樣的畫面,然後點選Convert to data binding layout,他就會幫你設計成包data的格式。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <!--寫viewmodel-->
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

那麼等等再回來改布局的部分,接著先建一個Model的class,我設計的model帶有兩個欄位(name、phone)。

public class Model {
    private String name;
    private String phone;
    public Model(String name, String phone){
        this.name=name;
        this.phone=phone;
    }
    public String getName() {
        return "你的名字是:"+name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return "你的電話是:"+phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
    //button的onclick方法,談布局時會再提
    public void click(View view){
        Toast.makeText(view.getContext(),"SEND",Toast.LENGTH_SHORT).show();
    }
}

因為是單向綁定,所以我們沒辦法透過綁定edittext來使用其輸入,但我們可以透過回到MainActivity來設計,首先先到布局調整資料。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <variable
            name="Model"
            type="com.example.databinding.Model" />
    </data>
    
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/textview"
            android:layout_width="178dp"
            android:layout_height="44dp"
            android:gravity="left"
            android:text="@{Model.name}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.536"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.263" />

        <TextView
            android:id="@+id/textview2"
            android:layout_width="178dp"
            android:layout_height="44dp"
            android:gravity="left"
            android:text="@{Model.phone}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.536"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.391" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="236dp"
            android:text="Button"
            android:onClick="@{Model::click}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

綁定的方法就是用自己variable設的name,另外透過getter來取得資料,像是@{Model.name}也就是從model裡面的getName方法來取得name值。
按鈕的話分很多種寫法,假設variable name是Model、而click是方法名,就像是:

android:onClick="@{Model.click}"
android:onClick="@{Model::click}"
android:onClick="@{{(view)->model.click(obj data(傳入資料),view(傳入view))}}"

大概還蠻多種的,但目前我比較常寫到的是這三種,按鈕都可以用這些方法來做監聽的動作,但都需要在你對應variable的type裡面宣告這個方法名。

public void click(View view){
//要做的事
}
//第三種(傳入資料、view)
public void click(obj data,View view){
//要做的事
}

大約是這樣,那麼接著看到MainActivity來input資料。

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        //ActivityMainBinding需先build(ctrl+f9)才會建立,使用Databinding的setContentView方法
        ActivityMainBinding binding = DataBindingUtil.setContentView(MainActivity.this,R.layout.activity_main);
        //建立data資料
        Model data = new Model("Android","0800-000-000");
        //設定資料
        binding.setModel(data);
    }
}

這樣就完成了簡易的databinding單向綁定,而雙向綁定則需要將model定義成ObservableField(如下)

public ObservableField<String> name = new ObservableField<>();
public ObservableField<String> phone = new ObservableField<>();

而佈局元件的綁定要多加"=",對edittext也綁定時,就能在edittext輸入值時,textview跟著顯示。
(以name來說,若以改為上面的ObservableField型態,在對應的元件都加入text屬性的綁定)

<!--edittext-->
android:text="@={Model.name}"
<!--textview-->
android:text="@={Model.name}"

這樣就算是簡單的雙向綁定了,另外其他更廣的應用可能就得使用@Bindable、@BindingAdapter或@InverseBindingAdapter。

成果

https://ithelp.ithome.com.tw/upload/images/20210909/20139259BmAKF3BESZ.jpg


上一篇
Day23 Android - RxJava+Post
下一篇
Day25 Android - MVP架構(簡易)
系列文
Android 新手入門學習30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言